package com.sxt.netty;

import org.springframework.stereotype.Component;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @模块目的/功能：Netty服务器端 
 * @版权说明： 
 * @版本号：1.0 
 * @日期：2019.11.13
 * @作者：罗林
 */
@Component
public class NettyServer {
	//端口号
	private Integer port;
	//
	private byte delimiter;
	//
	private EventLoopGroup bossGroup = null;
	//
	private EventLoopGroup workerGroup = null;

	/**
	 * @函数的名称:NettyServer
	 * @目的/功能:无参构造函数
	 * @输入参数:无
	 * @返回值:无
	 * @作者:罗林
	 * @日期:2019.11.13
	 */
	public NettyServer() {
		
	}
	/**
	 * @函数的名称:NettyServer
	 * @目的/功能:有参构造函数
	 * @输入参数:Integer port, byte delimiter
	 * @返回值:无
	 * @作者:罗林
	 * @日期:2019.11.13
	 */
	public NettyServer(Integer port, byte delimiter) {
        this.port = port;
        this.delimiter = delimiter;
    }
	/**
	 * @函数的名称:startServer
	 * @目的/功能:启动服务器
	 * @输入参数:Integer port
	 * @返回值:无
	 * @作者:罗林
	 * @日期:2019.11.13
	 */
	public void startServer() {
		/** 针对linux优化 */
		String osName = System.getProperty("os.name");
		/** 配置服务端的NIO线程组 */
		if (osName.equalsIgnoreCase("Linux")) {
			/** 负责服务端接收客户端的连接 */
			this.bossGroup = new EpollEventLoopGroup();
			/** 负责进行SocketChannel的网络读写 */
			this.workerGroup = new EpollEventLoopGroup();
		} else {
			/** 负责服务端接收客户端的连接 */
			this.bossGroup = new NioEventLoopGroup();
			/** 负责进行SocketChannel的网络读写 */
			this.workerGroup = new NioEventLoopGroup();
		}
		/** Netty启动Nio服务端的辅助类 */
		ServerBootstrap bootstrap = new ServerBootstrap();

		bootstrap.group(this.bossGroup, this.workerGroup)
				// keepAlive默认是打开
				.option(ChannelOption.SO_KEEPALIVE, true)// 保持连接
				.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000).option(ChannelOption.SO_SNDBUF, 1024 * 256) // 发包缓冲区，单位多少？
				.option(ChannelOption.SO_RCVBUF, 1024 * 256) // 收包缓冲区，单位多少？
				.option(ChannelOption.TCP_NODELAY, true); // TCP立即发包
		/** Linux平台用Epoll模式 **/
		if (osName.equals("Linux")) { // Linux平台用Epoll模式
			bootstrap.channel(EpollServerSocketChannel.class);
		} else {
			bootstrap.channel(NioServerSocketChannel.class);
		}

		/** 添加解码器、编码器 */
		
		bootstrap.childHandler(new MsgCoderHandler(this.delimiter));

		try {
			/** 绑定端口同步操作 */
			ChannelFuture future = bootstrap.bind(this.port).sync();
			/** 监听端口关闭(//等待客户端链路关闭) **/
			future.channel().closeFuture().sync();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			/** 优雅退出,释放资源 */
			// 关闭工作线程组
			this.workerGroup.shutdownGracefully();
			// 关闭主线程组
			this.bossGroup.shutdownGracefully();
		}
	}
}
